package com.vanzo.nfc;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.tech.Ndef;
import android.nfc.tech.NdefFormatable;
import android.os.Parcelable;

import com.vanzo.encryption.Encryption;
import com.vanzo.talkie.Follower;
import com.vanzo.util.LogUtil;

import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;

/**
 * Created by Administrator on 2018/1/31.
 */

public class NFCManager {

    private Activity activity;

    public NfcAdapter getNfcAdapter() {
        return nfcAdapter;
    }

    private NfcAdapter nfcAdapter;

    public NFCManager(Activity activity) {
        this.activity = activity;
    }

    public void verifyNFC() throws NFCNotSupported, NFCNotEnabled {

        nfcAdapter = NfcAdapter.getDefaultAdapter(activity);

        if (nfcAdapter == null) {
            throw new NFCNotSupported();
        }

        if (!nfcAdapter.isEnabled()) {
            throw new NFCNotEnabled();
        }
        Intent nfcIntent = new Intent(activity, activity.getClass());
        nfcIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(activity, 0, nfcIntent, 0);
        IntentFilter[] intentFiltersArray = new IntentFilter[]{};
        String[][] techList = new String[][]{
                {Ndef.class.getName()},
                {NdefFormatable.class.getName()}
        };
//        NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(activity);
        nfcAdapter.enableForegroundDispatch(activity, pendingIntent, intentFiltersArray, techList);
    }

    public void init() {

    }

    public static final int TRANSMITTING_TERMINAL = 1001;
    public static final int RECEIVING_TERMINAL = 1002;

    public void setTerminal(int terminal) {
        switch (terminal) {
            case TRANSMITTING_TERMINAL:
                break;
            case RECEIVING_TERMINAL:
                break;
            default:
                break;
        }

    }

    public void onResume() {
//        nfcAdapter.enableForegroundDispatch(activity, pendingIntent, intentFiltersArray, techList);
    }

    public void onPause() {

    }

    public void startBind() {
        nfcAdapter.setBeamPushUrisCallback(createBeamUrisCallback, activity);

        nfcAdapter.setNdefPushMessageCallback(createNdefMessageCallback, activity);

        nfcAdapter.setOnNdefPushCompleteCallback(onNdefPushCompleteCallback, activity);
    }

    public void sendNfc(NdefMessage message) {
        nfcAdapter.setNdefPushMessage(message, activity);
    }


    public void stopBind() {
        nfcAdapter.setBeamPushUrisCallback(null, activity);

        nfcAdapter.setNdefPushMessageCallback(null, activity);

        nfcAdapter.setOnNdefPushCompleteCallback(null, activity);
    }

    public NdefMessage createTextMessage(Follower follower) {
        return createTextMessage(follower.getNfc(), follower.getLength());
    }

    public NdefMessage createTextMessage(byte[] nfc, int len) {
        try {
            // Get UTF-8 byte
            int nfcLength = nfc.length;

            ByteArrayOutputStream payload = new ByteArrayOutputStream(nfcLength);
            payload.write(nfc, 0, nfcLength);
            NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
                    NdefRecord.RTD_TEXT, new byte[0],
                    payload.toByteArray());

            String lenString = len + "";
            LogUtil.put(this, "lenString = " + lenString, LogUtil.WARN);
            byte[] text = lenString.getBytes("UTF-8"); // Content in UTF-8

            int textLength = text.length;

            ByteArrayOutputStream payload1 = new ByteArrayOutputStream(textLength);
            payload1.write(text, 0, textLength);
            NdefRecord record1 = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
                    NdefRecord.RTD_TEXT, new byte[0],
                    payload1.toByteArray());

            return new NdefMessage(new NdefRecord[]{record, record1});
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    private NfcAdapter.CreateBeamUrisCallback createBeamUrisCallback;
    private NfcAdapter.CreateNdefMessageCallback createNdefMessageCallback;
    private NfcAdapter.OnNdefPushCompleteCallback onNdefPushCompleteCallback;

    public void setCallback(NfcAdapter.CreateBeamUrisCallback createBeamUrisCallback, NfcAdapter.CreateNdefMessageCallback createNdefMessageCallback, NfcAdapter.OnNdefPushCompleteCallback onNdefPushCompleteCallback) {

        this.createBeamUrisCallback = createBeamUrisCallback;
        this.createNdefMessageCallback = createNdefMessageCallback;
        this.onNdefPushCompleteCallback = onNdefPushCompleteCallback;
    }

    public Encryption.NFC readBinaryFromTag(Intent intent) {
        if (intent == null) return null;
        String lengthString = null;
        Parcelable[] rawArray = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
        if (rawArray == null) {
            return null;
        }
        NdefMessage mNdefMsg = (NdefMessage) rawArray[0];
        NdefRecord mNdefRecord = mNdefMsg.getRecords()[0];
        NdefRecord mNdefRecord1 = mNdefMsg.getRecords()[1];
        if (mNdefRecord != null) {
            try {
                lengthString = new String(mNdefRecord1.getPayload(), "UTF-8");
                LogUtil.put(this, "lengthString = " + lengthString, LogUtil.WARN);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            byte[] nfc;
            nfc = mNdefRecord.getPayload();
            try {
                if (Integer.parseInt(lengthString) >= 2100) {
                    LogUtil.put(this, "nfc length = " + lengthString, LogUtil.WARN);
                    return null;
                }
            } catch (NumberFormatException e) {
                return null;
            }
            Encryption.NFC binary = Encryption.parseNFCFromByte(nfc, Integer.parseInt(lengthString));
            return binary;
        }
        return null;
    }

    public static class NFCNotSupported extends Exception {
    }

    public static class NFCNotEnabled extends Exception {
    }
}
